/*
    SEL - Simple DirectMedia Layer Extension Library
    Copyright (C) 2001 Matej Knopp <knopp@users.sf.net>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#ifndef __sel_sdl_h__
#define __sel_sdl_h__

#include <SDL/SDL.h>
#include <cstdarg>

//! SDL namespace translation.
/*!
  The purpose of this namespace is to make SDL identifiers use namespaces
  and thus make the code more consistent.

  Many parts of the SEL documentation reference SDL identifiers translated
  by this namespace. So if you want to find out something about SDL::Surface
  mentioned in the SEL documentation you will have to look for SDL_Surface
  in the SDL documentation.

  This page should help you to find the original SDL identifiers.
 */
namespace SDL {

/************************************************************************
 ** file SDL_rwops.h                                                   **
 ************************************************************************/

typedef SDL_RWops RWops;

inline SDL::RWops * RWFromFile (const char *file, const char *mode)
{
	return SDL_RWFromFile (file, mode);
}

inline SDL::RWops * RWFromFP (FILE *fp, bool autoclose)
{
        return SDL_RWFromFP (fp, autoclose);
}

inline SDL::RWops * RWFromMem (void *mem, int size)
{
        return SDL_RWFromMem (mem, size);
}

inline SDL::RWops * AllocRW (void)
{
	return SDL_AllocRW ();
}

inline void FreeRW (SDL::RWops *area)
{
	SDL_FreeRW (area);
}

inline int RWseek (SDL::RWops *ctx, int offset, int whence)
{
	return SDL_RWseek (ctx, offset, whence);
}

inline int RWtell (SDL::RWops *ctx)
{
	return SDL_RWtell (ctx);
}

inline int RWread (SDL::RWops *ctx, void *ptr, int size, int maxnum)
{
        return SDL_RWread (ctx, ptr, size, maxnum);
}

inline int RWwrite (SDL::RWops *ctx, const void *ptr, int size, int num)
{
	return SDL_RWwrite (ctx, ptr, size, num);
}

inline int RWclose (SDL::RWops *ctx)
{
	return SDL_RWclose (ctx);
}

/************************************************************************
 ** file SDL_video.h                                                   **
 ************************************************************************/

const Uint8 ALPHA_OPAQUE = SDL_ALPHA_OPAQUE;
const Uint8 ALPHA_TRANSPARENT = SDL_ALPHA_TRANSPARENT;

typedef SDL_Rect Rect;
typedef SDL_Color Color;
typedef SDL_Palette Palette;
typedef SDL_PixelFormat PixelFormat;
typedef SDL_Surface Surface;

/* Surface flags */
enum
{
	SWSURFACE   = SDL_SWSURFACE,
    HWSURFACE   = SDL_HWSURFACE,
    ASYNCBLIT   = SDL_ASYNCBLIT,

    ANYFORMAT   = SDL_ANYFORMAT,
    HWPALETTE   = SDL_HWPALETTE,
    DOUBLEBUF   = SDL_DOUBLEBUF,
    FULLSCREEN  = SDL_FULLSCREEN,
    OPENGL      = SDL_OPENGL,
    OPENGLBLIT  = SDL_OPENGLBLIT,
    RESIZABLE   = SDL_RESIZABLE,
    NOFRAME     = SDL_NOFRAME,

    HWACCEL     = SDL_HWACCEL,
    SRCCOLORKEY = SDL_SRCCOLORKEY,
    RLEACCELOK  = SDL_RLEACCELOK,
    RLEACCEL    = SDL_RLEACCEL,
    SRCALPHA    = SDL_SRCALPHA,
    PREALLOC    = SDL_PREALLOC
};

inline bool MUSTLOCK (SDL::Surface *surface)
{
	return SDL_MUSTLOCK (surface);
}

typedef SDL_VideoInfo VideoInfo;

enum
{
        YV12_OVERLAY = SDL_YV12_OVERLAY,
        IYUV_OVERLAY = SDL_IYUV_OVERLAY,
        YUY2_OVERLAY = SDL_YUY2_OVERLAY,
        UYVY_OVERLAY = SDL_UYVY_OVERLAY,
        YVYU_OVERLAY = SDL_YVYU_OVERLAY
};

typedef SDL_Overlay Overlay;

typedef SDL_GLattr GLattr;

namespace GL
{

const SDL::GLattr
	RED_SIZE         = SDL_GL_RED_SIZE,
	GREEN_SIZE       = SDL_GL_GREEN_SIZE,
	BLUE_SIZE        = SDL_GL_BLUE_SIZE,
	ALPHA_SIZE       = SDL_GL_ALPHA_SIZE,
	BUFFER_SIZE      = SDL_GL_BUFFER_SIZE,
	DOUBLEBUFER      = SDL_GL_DOUBLEBUFFER,
	DEPTH_SIZE       = SDL_GL_DEPTH_SIZE,
	STENCIL_SIZE     = SDL_GL_STENCIL_SIZE,
	ACCUM_RED_SIZE   = SDL_GL_ACCUM_RED_SIZE,
	ACCUM_GREEN_SIZE = SDL_GL_ACCUM_GREEN_SIZE,
	ACCUM_BLUE_SIZE  = SDL_GL_ACCUM_BLUE_SIZE,
	ACCUM_ALPHA_SIZE = SDL_GL_ACCUM_ALPHA_SIZE;

} // namespace GL

enum
{
	LOGPAL  = SDL_LOGPAL,
        PHYSPAL = SDL_PHYSPAL
};

inline int VideoInit (const char *driver_name, Uint32 flags)
{
	return SDL_VideoInit (driver_name, flags);
}

inline void VideoQuit (void)
{
	SDL_VideoQuit ();
}

inline char *VideoDriverName (char *namebuf, int maxlen)
{
	return SDL_VideoDriverName (namebuf, maxlen);
}

inline SDL::Surface *GetVideoSurface (void)
{
	return SDL_GetVideoSurface ();
}

inline const SDL::VideoInfo * GetVideoInfo ()
{
	return SDL_GetVideoInfo ();
}

inline int VideoModeOK (int width, int height, int bpp, Uint32 flags)
{
	return SDL_VideoModeOK (width, height, bpp, flags);
}

inline SDL::Rect ** ListModes (SDL::PixelFormat *format, Uint32 flags)
{
	return SDL_ListModes (format, flags);
}

inline SDL::Surface *SetVideoMode (int width, int height, int bpp,
				   Uint32 flags)
{
	return SDL_SetVideoMode (width, height, bpp, flags);
}

inline void UpdateRects (SDL::Surface *screen, int numrects,
			 SDL::Rect *rects)
{
	SDL_UpdateRects (screen, numrects, rects);
}

inline void UpdateRect (SDL::Surface *screen, Sint32 x, Sint32 y,
			Uint32 w, Uint32 h)
{
        SDL_UpdateRect (screen, x, y, w, h);
}

inline int Flip (SDL::Surface *screen)
{
	return SDL_Flip (screen);
}

inline int SetGamma (float red, float green, float blue)
{
	return SDL_SetGamma (red, green, blue);
}

inline int SetGammaRamp (Uint16 *red, Uint16 *green, Uint16 *blue)
{
	return SDL_SetGammaRamp (red, green, blue);
}

inline int GetGammaRamp (Uint16 *red, Uint16 *green, Uint16 *blue)
{
	return SDL_GetGammaRamp (red, green, blue);
}

inline int SetColors (SDL::Surface *surface, SDL::Color *colors,
		      int firstcolor, int ncolors)
{
	return SDL_SetColors (surface, colors, firstcolor, ncolors);
}

inline int SetPalette (SDL::Surface *surface, int flags,
		       SDL::Color *colors, int firstcolor, int ncolors)
{
	return SDL_SetPalette (surface, flags, colors, firstcolor, ncolors);
}

inline Uint32 MapRGB (SDL::PixelFormat *format, Uint8 r, Uint8 g, Uint8 b)
{
	return SDL_MapRGB (format, r, g, b);
}

inline Uint32 MapRGBA (SDL::PixelFormat *format, Uint8 r, Uint8 g,
		       Uint8 b, Uint8 a)
{
	return SDL_MapRGBA (format, r, g, b, a);
}

inline void GetRGB (Uint32 pixel, SDL::PixelFormat *format, Uint8 *r,
		      Uint8 *g, Uint8 *b)
{
	SDL_GetRGB (pixel, format, r, g, b);
}

inline void GetRGBA (Uint32 pixel, SDL::PixelFormat *format, Uint8 *r,
		      Uint8 *g, Uint8 *b, Uint8 *a)
{
	SDL_GetRGBA (pixel, format, r, g, b, a);
}

inline SDL::Surface *CreateRGBSurface (Uint32 flags, int width, int height,
				       int depth, Uint32 Rmask, Uint32 Gmask,
                                       Uint32 Bmask, Uint32 Amask)
{
	return SDL_CreateRGBSurface (flags, width, height, depth, Rmask,
        			     Gmask, Bmask, Amask);
}

inline SDL::Surface *CreateRGBSurfaceFrom (void *pixels, int width,
					   int height, int depth, int pitch,
                                           Uint32 Rmask, Uint32 Gmask,
                                           Uint32 Bmask, Uint32 Amask)
{
	return SDL_CreateRGBSurfaceFrom (pixels, width, height, depth,
        				 pitch, Rmask, Gmask, Bmask, Amask);
}

inline void FreeSurface (SDL::Surface *surface)
{
	SDL_FreeSurface (surface);
}

inline int LockSurface (SDL::Surface *surface)
{
	return SDL_LockSurface (surface);
}

inline void UnlockSurface (SDL::Surface *surface)
{
	SDL_UnlockSurface (surface);
}

inline SDL::Surface *LoadBMP_RW (SDL::RWops *src, int freesrc)
{
        return SDL_LoadBMP_RW (src, freesrc);
}

inline SDL::Surface *LoadBMP (const char *filename)
{
	return SDL_LoadBMP (filename);
}

inline int SaveBMP_RW (SDL::Surface *surface, SDL::RWops *dst,
		       int freedst)
{
        return SDL_SaveBMP_RW (surface, dst, freedst);
}

inline int SaveBMP (SDL::Surface *surface, const char *filename)
{
	return SDL_SaveBMP (surface, filename);
}

inline int SetColorKey (SDL::Surface *surface, Uint32 flag, Uint32 key)
{
	return SDL_SetColorKey (surface, flag, key);
}

inline int SetAlpha (SDL::Surface *surface, Uint32 flag, Uint8 alpha)
{
	return SDL_SetAlpha (surface, flag, alpha);
}

inline bool SetClipRect (SDL::Surface *surface, SDL::Rect *rect)
{
	return SDL_SetClipRect (surface, rect);
}

inline void GetClipRect (SDL::Surface *surface, SDL::Rect *rect)
{
	return SDL_GetClipRect (surface, rect);
}

inline SDL::Surface *ConvertSurface (SDL::Surface *src,
				     SDL::PixelFormat *fmt, Uint32 flags)
{
	return SDL_ConvertSurface (src, fmt, flags);
}

inline int UpperBlit (SDL::Surface *src, SDL::Rect *srcrect,
		      SDL::Surface *dst, SDL::Rect *dstrect)
{
	return SDL_UpperBlit (src, srcrect, dst, dstrect);
}

inline int LowerBlit (SDL::Surface *src, SDL::Rect *srcrect,
                      SDL::Surface *dst, SDL::Rect *dstrect)
{
	return SDL_LowerBlit (src, srcrect, dst, dstrect);
}

inline int BlitSurface (SDL::Surface *src, SDL::Rect *srcrect,
			SDL::Surface *dst, SDL::Rect *dstrect)
{
	return SDL_BlitSurface (src, srcrect, dst, dstrect);
}

inline int FillRect (SDL::Surface *dst, SDL::Rect *dstrect, Uint32 color)
{
	return SDL_FillRect (dst, dstrect, color);
}

inline SDL::Surface *DisplayFormat (SDL::Surface *surface)
{
        return SDL_DisplayFormat (surface);
}

inline SDL::Surface *DisplayFormatAlpha (SDL::Surface *surface)
{
	return SDL_DisplayFormatAlpha (surface);
}

/* overlays */

inline SDL::Overlay *CreateYUVOverlay (int width, int height,
				       Uint32 format, SDL::Surface *display)
{
	return SDL_CreateYUVOverlay (width, height, format, display);
}

inline int LockYUVOverlay (SDL::Overlay *overlay)
{
	return SDL_LockYUVOverlay (overlay);
}

inline void UnlockYUVOverlay (SDL::Overlay *overlay)
{
	SDL_UnlockYUVOverlay (overlay);
}

inline int DisplayYUVOverlay (SDL::Overlay *overlay, SDL::Rect *dstrect)
{
        return SDL_DisplayYUVOverlay (overlay, dstrect);
}

inline void FreeYUVOverlay (SDL::Overlay *overlay)
{
	SDL_FreeYUVOverlay (overlay);
}

/* open gl */

namespace GL
{

inline int LoadLibrary (const char *path)
{
	return SDL_GL_LoadLibrary (path);
}

inline void *GetProcAddress (const char *proc)
{
	return SDL_GL_GetProcAddress (proc);
}

inline int SetAttribute (SDL::GLattr attr, int value)
{
	return SDL_GL_SetAttribute (attr, value);
}

inline int GetAttribute (SDL::GLattr attr, int *value)
{
	return SDL_GL_GetAttribute (attr, value);
}

inline void SwapBuffers (void)
{
	SDL_GL_SwapBuffers ();
}

inline void UpdateRects (int numrects, SDL::Rect *rects)
{
	return SDL_GL_UpdateRects (numrects, rects);
}

inline void Lock (void)
{
	SDL_GL_Lock ();
}

inline void Unlock (void)
{
	SDL_GL_Unlock ();
}

} // namespace GL

/* window manager */

typedef SDL_GrabMode GrabMode;

const SDL::GrabMode
	GRAB_QUERY      = SDL_GRAB_QUERY,
	GRAB_OFF        = SDL_GRAB_OFF,
	GRAB_ON         = SDL_GRAB_ON,
	GRAB_FULLSCREEN = SDL_GRAB_FULLSCREEN;

namespace WM
{

inline void SetCaption (const char *title, const char *icon)
{
	SDL_WM_SetCaption (title, icon);
}

inline void GetCaption (char **title, char **icon)
{
	SDL_WM_GetCaption (title, icon);
}

inline void SetIcon (SDL::Surface *icon, Uint8 *mask)
{
	SDL_WM_SetIcon (icon, mask);
}

inline int IconifyWindow (void)
{
	return SDL_WM_IconifyWindow ();
}

inline int ToggleFullScreen (SDL::Surface *surface)
{
	return SDL_WM_ToggleFullScreen (surface);
}

inline SDL::GrabMode GrabInput (SDL::GrabMode mode)
{
	return SDL_WM_GrabInput (mode);
}

} // namespace WM

/************************************************************************
 ** file SDL_events.h                                                  **
 ************************************************************************/

enum
{
	NOEVENT         = SDL_NOEVENT,
	ACTIVEEVENT     = SDL_ACTIVEEVENT,
	KEYDOWN         = SDL_KEYDOWN,
	KEYUP           = SDL_KEYUP,
	MOUSEMOTION     = SDL_MOUSEMOTION,
	MOUSEBUTTONDOWN = SDL_MOUSEBUTTONDOWN,
	MOUSEBUTTONUP   = SDL_MOUSEBUTTONUP,
	JOYAXISMOTION   = SDL_JOYAXISMOTION,
	JOYBALLMOTION   = SDL_JOYBALLMOTION,
	JOYHATMOTION    = SDL_JOYHATMOTION,
	JOYBUTTONDOWN   = SDL_JOYBUTTONDOWN,
	JOYBUTTONUP     = SDL_JOYBUTTONUP,
	QUIT            = SDL_QUIT,
	SYSWMEVENT      = SDL_SYSWMEVENT,
	RESERVEDA       = SDL_EVENT_RESERVEDA,
	RESERVEDB       = SDL_EVENT_RESERVEDB,
	VIDEORESIZE     = SDL_VIDEORESIZE,
	VIDEOEXPOSE     = SDL_VIDEOEXPOSE,
	EVENT_RESERVED2 = SDL_EVENT_RESERVED2,
	EVENT_RESERVED3 = SDL_EVENT_RESERVED3,
	EVENT_RESERVED4 = SDL_EVENT_RESERVED4,
	EVENT_RESERVED5 = SDL_EVENT_RESERVED5,
	EVENT_RESERVED6 = SDL_EVENT_RESERVED6,
	EVENT_RESERVED7 = SDL_EVENT_RESERVED7,

	USER_EVENT      = SDL_USEREVENT,

	NUMEVENTS       = SDL_NUMEVENTS
};

// Just for fun :)
inline Uint32 EVENTMASK (Uint32 x) { return 1 << x; }

enum {
	ACTIVEEVENTMASK	    = SDL_ACTIVEEVENTMASK,
	KEYDOWNMASK         = SDL_KEYDOWNMASK,
	KEYUPMASK           = SDL_KEYUPMASK,
	MOUSEMOTIONMASK     = SDL_MOUSEMOTIONMASK,
	MOUSEBUTTONDOWNMASK = SDL_MOUSEBUTTONDOWNMASK,
	MOUSEBUTTONUPMASK   = SDL_MOUSEBUTTONUPMASK,
	MOUSEEVENTMASK      = SDL_MOUSEEVENTMASK,
	JOYAXISMOTIONMASK   = SDL_JOYAXISMOTIONMASK,
	JOYBALLMOTIONMASK   = SDL_JOYBALLMOTIONMASK,
	JOYHATMOTIONMASK    = SDL_JOYHATMOTIONMASK,
	JOYBUTTONDOWNMASK   = SDL_JOYBUTTONDOWNMASK,
	JOYBUTTONUPMASK     = SDL_JOYBUTTONUPMASK,
	JOYEVENTMASK        = SDL_JOYEVENTMASK,
	VIDEORESIZEMASK     = SDL_VIDEORESIZEMASK,
	VIDEOEXPOSEMASK	    = SDL_VIDEOEXPOSEMASK,
	QUITMASK            = SDL_QUITMASK,
	SYSWMEVENTMASK      = SDL_SYSWMEVENTMASK
};

typedef SDL_ActiveEvent ActiveEvent;
typedef SDL_KeyboardEvent KeyboardEvent;
typedef SDL_MouseMotionEvent MouseMotionEvent;
typedef SDL_MouseButtonEvent MouseButtonEvent;
typedef SDL_JoyAxisEvent JoyAxisEvent;
typedef SDL_JoyBallEvent JoyBallEvent;
typedef SDL_JoyHatEvent JoyHatEvent;
typedef SDL_JoyButtonEvent JoyButtonEvent;
typedef SDL_ResizeEvent ResizeEvent;
typedef SDL_ExposeEvent ExposeEvent;
typedef SDL_QuitEvent QuitEvent;
typedef SDL_UserEvent UserEvent;
typedef SDL_SysWMEvent SysWMEvent;
typedef SDL_Event Event;

inline void PumpEvents (void)
{
	SDL_PumpEvents ();
}

typedef SDL_eventaction eventaction;

const SDL::eventaction
	ADDEVENT  = SDL_ADDEVENT,
	PEEKEVENT = SDL_PEEKEVENT,
	GETEVENT  = SDL_GETEVENT;

inline int PeepEvents (SDL::Event *events, int numevents,
		       SDL::eventaction action, Uint32 mask)
{
	return SDL_PeepEvents (events, numevents, action, mask);
}

inline int PollEvent (SDL::Event *event)
{
	return SDL_PollEvent (event);
}

inline int WaitEvent (SDL::Event *event)
{
	return SDL_WaitEvent (event);
}

inline int PushEvent (SDL::Event *event)
{
	return SDL_PushEvent (event);
}

typedef SDL_EventFilter EventFilter;

inline void SetEventFilter (SDL::EventFilter filter)
{
	SDL_SetEventFilter (filter);
}

inline SDL::EventFilter GetEventFilter (void)
{
	return SDL_GetEventFilter ();
}

enum
{
	QUERY = SDL_QUERY,
	IGNORE = SDL_IGNORE,
	DISABLE = SDL_DISABLE,
	ENABLE = SDL_ENABLE
};

inline Uint8 EventState (Uint8 type, int state)
{
	return SDL_EventState (type, state);
}

/************************************************************************
 ** file SDL_types.h                                                   **
 ************************************************************************/

enum
{
	PRESSED = SDL_PRESSED,
	RELEASED = SDL_RELEASED
};

/************************************************************************
 ** file SDL_audio.h                                                   **
 ************************************************************************/

typedef SDL_AudioSpec AudioSpec;
typedef SDL_AudioCVT AudioCVT;

inline int AudioInit (const char *driver_name)
{
	return SDL_AudioInit (driver_name);
}

inline void AudioQuit (void)
{
	SDL_AudioQuit ();
}

inline char *AudioDriverName (char *namebuf, int maxlen)
{
	return SDL_AudioDriverName (namebuf, maxlen);
}

inline int OpenAudio (SDL::AudioSpec *desired, SDL::AudioSpec *obtained)
{
	return SDL_OpenAudio (desired, obtained);
}

typedef SDL_audiostatus audiostatus;

const SDL::audiostatus
	AUDIO_STOPPED = SDL_AUDIO_STOPPED,
	AUDIO_PLAYING = SDL_AUDIO_PLAYING,
	AUDIO_PAUSED  = SDL_AUDIO_PAUSED;

inline SDL::audiostatus GetAudioStatus (void)
{
	return SDL_GetAudioStatus ();
}

inline void PauseAudio (bool pause_on)
{
	SDL_PauseAudio (pause_on);
}

inline SDL::AudioSpec *LoadWAV_RW (SDL::RWops *src, int freesrc,
				   SDL::AudioSpec *spec, Uint8 **audio_buf,
				   Uint32 *audio_len)
{
	return SDL_LoadWAV_RW (src, freesrc, spec, audio_buf, audio_len);
}

inline SDL::AudioSpec *LoadWAV (const char *filename, SDL::AudioSpec *spec,
				Uint8 **audio_buf, Uint32 *audio_len)
{
	return SDL_LoadWAV (filename, spec, audio_buf, audio_len);
}

inline void FreeWAV (Uint8 *audio_buf)
{
	SDL_FreeWAV (audio_buf);
}

inline int BuildAudioCVT (SDL::AudioCVT *cvt, Uint16 srcformat,
			  Uint8 srcchannels, int srcrate,
			  Uint16 dstformat, Uint8 dstchannels, int dstrate)
{
	return SDL_BuildAudioCVT (cvt, srcformat, srcchannels, srcrate,
				  dstformat, dstchannels, dstrate);
}

inline int ConvertAudio (SDL::AudioCVT *cvt)
{
	return SDL_ConvertAudio (cvt);
}

const int MIX_MAXVOLUME = 128;

inline void MixAudio (Uint8 *dst, Uint8 *src, Uint32 len, int volume)
{
	SDL_MixAudio (dst, src, len, volume);
}

inline void LockAudio (void)
{
	SDL_LockAudio ();
}

inline void UnlockAudio (void)
{
	SDL_UnlockAudio ();
}

inline void CloseAudio (void)
{
	SDL_CloseAudio ();
}

/************************************************************************
 ** file SDL_endian.h                                                  **
 ************************************************************************/

#include <SDL/SDL_endian.h>

inline Uint16 Swap16 (Uint16 x)
{
	return SDL_Swap16 (x);
}

inline Uint16 Swap16 (Uint32 x)
{
	return SDL_Swap16 (x);
}

inline Uint16 Swap16 (Uint64 x)
{
	return SDL_Swap16 (x);
}

inline Sint16 Swap16 (Sint16 x)
{
	return SDL_Swap16 (x);
}

inline Sint16 Swap16 (Sint32 x)
{
	return SDL_Swap16 (x);
}

inline Sint16 Swap16 (Sint64 x)
{
	return SDL_Swap16 (x);
}

inline Uint32 Swap32 (Uint32 x)
{
	return SDL_Swap32 (x);
}

inline Uint32 Swap32 (Uint64 x)
{
	return SDL_Swap32 (x);
}

inline Sint32 Swap32 (Sint32 x)
{
	return SDL_Swap32 (x);
}

inline Sint32 Swap32 (Sint64 x)
{
	return SDL_Swap32 (x);
}

inline Uint64 Swap64 (Uint64 x)
{
	return SDL_Swap64 (x);
}

inline Sint64 Swap64 (Sint64 x)
{
	return SDL_Swap64 (x);
}

// The macro below generates SDL::Swap functions for all possible
// integer types (signed and unsigned). This ensures that always
// the correct type of integer will be returned.

#define __GENERATE_SWAP_FUNCTION(sign, size, endian, input_size) \
	inline sign##int##size Swap##endian##size (sign##int##input_size x) \
	{ return SDL_Swap##endian##size (x); }

__GENERATE_SWAP_FUNCTION (S, 16, LE, 16);
__GENERATE_SWAP_FUNCTION (U, 16, LE, 16);
__GENERATE_SWAP_FUNCTION (S, 16, LE, 32);
__GENERATE_SWAP_FUNCTION (U, 16, LE, 32);
__GENERATE_SWAP_FUNCTION (S, 16, LE, 64);
__GENERATE_SWAP_FUNCTION (U, 16, LE, 64);

__GENERATE_SWAP_FUNCTION (S, 32, LE, 32);
__GENERATE_SWAP_FUNCTION (U, 32, LE, 32);
__GENERATE_SWAP_FUNCTION (S, 32, LE, 64);
__GENERATE_SWAP_FUNCTION (U, 32, LE, 64);

__GENERATE_SWAP_FUNCTION (S, 64, LE, 64);
__GENERATE_SWAP_FUNCTION (U, 64, LE, 64);

__GENERATE_SWAP_FUNCTION (S, 16, BE, 16);
__GENERATE_SWAP_FUNCTION (U, 16, BE, 16);
__GENERATE_SWAP_FUNCTION (S, 16, BE, 32);
__GENERATE_SWAP_FUNCTION (U, 16, BE, 32);
__GENERATE_SWAP_FUNCTION (S, 16, BE, 64);
__GENERATE_SWAP_FUNCTION (U, 16, BE, 64);

__GENERATE_SWAP_FUNCTION (S, 32, BE, 32);
__GENERATE_SWAP_FUNCTION (U, 32, BE, 32);
__GENERATE_SWAP_FUNCTION (S, 32, BE, 64);
__GENERATE_SWAP_FUNCTION (U, 32, BE, 64);

__GENERATE_SWAP_FUNCTION (S, 64, BE, 64);
__GENERATE_SWAP_FUNCTION (U, 64, BE, 64);

#undef __GENERATE_SWAP_FUNCTION

inline Uint16 ReadLE16 (SDL::RWops *src)
{
	return SDL_ReadLE16 (src);
}

inline Uint16 ReadBE16 (SDL::RWops *src)
{
	return SDL_ReadBE16 (src);
}

inline Uint32 ReadLE32 (SDL::RWops *src)
{
	return SDL_ReadLE32 (src);
}

inline Uint32 ReadBE32 (SDL::RWops *src)
{
	return SDL_ReadBE32 (src);
}

inline Uint64 ReadLE64 (SDL::RWops *src)
{
	return SDL_ReadLE64 (src);
}

inline Uint64 ReadBE64 (SDL::RWops *src)
{
	return SDL_ReadBE64 (src);
}

inline int WriteLE16 (SDL::RWops *dst, Uint16 value)
{
	return SDL_WriteLE16 (dst, value);
}

inline int WriteBE16 (SDL::RWops *dst, Uint16 value)
{
	return SDL_WriteBE16 (dst, value);
}

inline int WriteLE32 (SDL::RWops *dst, Uint32 value)
{
	return SDL_WriteLE32 (dst, value);
}

inline int WriteBE32 (SDL::RWops *dst, Uint32 value)
{
	return SDL_WriteBE32 (dst, value);
}

inline int WriteLE64 (SDL::RWops *dst, Uint64 value)
{
	return SDL_WriteLE64 (dst, value);
}

inline int WriteBE64 (SDL::RWops *dst, Uint64 value)
{
	return SDL_WriteBE64 (dst, value);
}

/************************************************************************
 ** file SDL_joystick.h                                                **
 ************************************************************************/

typedef SDL_Joystick Joystick;

inline int NumJoysticks (void)
{
	return SDL_NumJoysticks ();
}

inline const char *JoystickName (int device_index)
{
	return SDL_JoystickName (device_index);
}

inline SDL::Joystick *JoystickOpen (int device_index)
{
	return SDL_JoystickOpen (device_index);
}

inline int JoystickOpened (int device_index)
{
	return SDL_JoystickOpened (device_index);
}

inline int JoystickIndex (SDL::Joystick *joystick)
{
	return SDL_JoystickIndex (joystick);
}

inline int JoystickNumAxes (SDL::Joystick *joystick)
{
	return SDL_JoystickNumAxes (joystick);
}

inline int JoystickNumBalls (SDL::Joystick *joystick)
{
	return SDL_JoystickNumBalls (joystick);
}

inline int JoystickNumHats (SDL::Joystick *joystick)
{
	return SDL_JoystickNumHats (joystick);
}

inline int JoystickNumButtons (SDL::Joystick *joystick)
{
	return SDL_JoystickNumButtons (joystick);
}

inline void JoystickUpdate (void)
{
	SDL_JoystickUpdate ();
}

inline int JoystickEventState (int state)
{
	return SDL_JoystickEventState (state);
}

inline Sint16 JoystickGetAxis (SDL::Joystick *joystick, int axis)
{
	return SDL_JoystickGetAxis (joystick, axis);
}

enum
{
	HAT_CENTERED  = SDL_HAT_CENTERED,
	HAT_UP        = SDL_HAT_UP,
	HAT_RIGHT     = SDL_HAT_RIGHT,
	HAT_DOWN      = SDL_HAT_DOWN,
	HAT_LEFT      = SDL_HAT_LEFT,
	HAT_RIGHTUP   = SDL_HAT_RIGHTUP,
	HAT_RIGHTDOWN = SDL_HAT_RIGHTDOWN,
	HAT_LEFTUP    = SDL_HAT_LEFTUP,
	HAT_LEFTDOWN  = SDL_HAT_LEFTDOWN
};

inline Uint8 JoystickGetHat (SDL::Joystick *joystick, int hat)
{
	return SDL_JoystickGetHat (joystick, hat);
}

inline int JoystickGetBall (SDL::Joystick *joystick, int ball, int *dx, int *dy)
{
	return SDL_JoystickGetBall (joystick, ball, dx, dy);
}

inline Uint8 JoystickGetButton (SDL::Joystick *joystick, int button)
{
	return SDL_JoystickGetButton (joystick, button);
}

inline void JoystickClose (SDL::Joystick *joystick)
{
	SDL_JoystickClose (joystick);
}

/************************************************************************
 ** file SDL_keyboard.h                                                **
 ************************************************************************/

typedef SDL_keysym keysym;

const Uint32
	ALL_HOTKEYS = SDL_ALL_HOTKEYS;

inline int EnableUNICODE (int enable)
{
	return SDL_EnableUNICODE (enable);
}

const int
	DEFAULT_REPEAT_DELAY    = SDL_DEFAULT_REPEAT_DELAY,
	DEFAULT_REPEAT_INTERVAL = SDL_DEFAULT_REPEAT_INTERVAL;

inline int EnableKeyRepeat (int delay, int interval)
{
	return SDL_EnableKeyRepeat (delay, interval);
}

inline Uint8* GetKeyState (int *numkeys)
{
	return SDL_GetKeyState (numkeys);
}

inline SDLMod GetModState (void)
{
	return SDL_GetModState ();
}

inline void SetModState (SDLMod modstate)
{
	SDL_SetModState (modstate);
}

inline char *GetKeyName (SDLKey key)
{
	return SDL_GetKeyName (key);
}

/************************************************************************
 ** file SDL_mouse.h                                                   **
 ************************************************************************/

typedef SDL_Cursor Cursor;

inline Uint8 GetMouseState (int *x, int *y)
{
	return SDL_GetMouseState (x, y);
}

inline Uint8 GetRelativeMouseState (int *x, int *y)
{
	return SDL_GetRelativeMouseState (x, y);
}

inline void WarpMouse (Uint16 x, Uint16 y)
{
	SDL_WarpMouse (x, y);
}

inline SDL::Cursor *CreateCursor (Uint8 *data, Uint8 *mask, int w, int h,
				  int hot_x, int hot_y)
{
	return SDL_CreateCursor (data, mask, w, h, hot_x, hot_y);
}

inline void SetCursor (SDL::Cursor *cursor)
{
	return SDL_SetCursor (cursor);
}

inline SDL::Cursor *GetCursor (void)
{
	return SDL_GetCursor ();
}

inline void FreeCursor (SDL::Cursor *cursor)
{
	SDL_FreeCursor (cursor);
}

inline int ShowCursor (int toggle)
{
	return SDL_ShowCursor (toggle);
}

inline Uint32 BUTTON (Uint32 x)
{
	return SDL_BUTTON (x);
}

enum
{
	BUTTON_LEFT   = SDL_BUTTON_LEFT,
	BUTTON_MIDDLE = SDL_BUTTON_MIDDLE,
	BUTTON_RIGHT  = SDL_BUTTON_RIGHT,
	BUTTON_LMASK  = SDL_BUTTON_LMASK,
	BUTTON_MMASK  = SDL_BUTTON_MMASK,
	BUTTON_RMASK  = SDL_BUTTON_RMASK
};

/************************************************************************
 ** file SDL_mutex.h                                                   **
 ************************************************************************/

/* mutex */

const Uint32
	MUTEX_TIMEDOUT = SDL_MUTEX_TIMEDOUT,
	MUTEX_MAXWAIT  = SDL_MUTEX_MAXWAIT;

typedef SDL_mutex mutex;

inline SDL::mutex *CreateMutex (void)
{
	return SDL_CreateMutex ();
}

inline int LockMutex (SDL::mutex *mutex)
{
	return SDL_LockMutex (mutex);
}

inline int mutexP (SDL::mutex *mutex)
{
	return SDL_mutexP (mutex);
}

inline int UnlockMutex (SDL::mutex *mutex)
{
	return SDL_UnlockMutex (mutex);
}

inline int mutexV (SDL::mutex *mutex)
{
	return SDL_mutexV (mutex);
}

inline void DestroyMutex (SDL::mutex *mutex)
{
	SDL_DestroyMutex (mutex);
}

/* semaphore */

typedef SDL_sem sem;

inline SDL::sem *CreateSemaphore (Uint32 initial_value)
{
	return SDL_CreateSemaphore (initial_value);
}

inline void DestroySemaphore (SDL::sem *sem)
{
	SDL_DestroySemaphore (sem);
}

inline int SemWait (SDL::sem *sem)
{
	return SDL_SemWait (sem);
}

inline int SemWaitTimeout (SDL::sem *sem, Uint32 ms)
{
	return SDL_SemWaitTimeout (sem, ms);
}


inline int SemTryWait (SDL::sem *sem)
{
	return SDL_SemTryWait (sem);
}

inline int SemPost (SDL::sem *post)
{
	return SDL_SemPost (post);
}

inline Uint32 SemValue (SDL::sem *sem)
{
	return SDL_SemValue (sem);
}

/* condition variable */

typedef SDL_cond cond;

inline SDL::cond *CreateCond (void)
{
	return SDL_CreateCond ();
}

inline void DestroyCond (SDL::cond *cond)
{
	SDL_DestroyCond (cond);
}

inline int CondSignal (SDL::cond *cond)
{
	return SDL_CondSignal (cond);
}

inline int CondBroadcast (SDL::cond *cond)
{
	return SDL_CondBroadcast (cond);
}

inline int CondWait (SDL::cond *cond, SDL::mutex *mutex)
{
	return SDL_CondWait (cond, mutex);
}

inline int CondWaitTimeout (SDL::cond *cond, SDL::mutex *mutex, Uint32 ms)
{
	return SDL_CondWaitTimeout (cond, mutex, ms);
}

/************************************************************************
 ** file SDL_thread.h                                                  **
 ************************************************************************/

#include <SDL/SDL_thread.h>

typedef SDL_Thread Thread;

inline SDL::Thread *CreateThread (int (*fn) (void*), void *data)
{
	return SDL_CreateThread (fn, data);
}

inline Uint32 ThreadID (void)
{
	return SDL_ThreadID ();
}

inline Uint32 GetThreadID (SDL::Thread *thread)
{
	return SDL_GetThreadID (thread);
}

inline void WaitThread (SDL::Thread *thread, int *status)
{
	SDL_WaitThread (thread, status);
}

inline void KillThread (SDL::Thread *thread)
{
	SDL_KillThread (thread);
}

/************************************************************************
 ** file SDL_timer.h                                                   **
 ************************************************************************/

const int TIMESLICE = 10;

inline Uint32 GetTicks (void)
{
	return SDL_GetTicks ();
}

inline void Delay (Uint32 ms)
{
	return SDL_Delay (ms);
}

typedef SDL_TimerCallback TimerCallback;

inline int SetTimer (Uint32 interval, SDL::TimerCallback callback)
{
	return SDL_SetTimer (interval, callback);
}

typedef SDL_NewTimerCallback NewTimerCallback;

typedef SDL_TimerID TimerID;

inline SDL::TimerID AddTimer (Uint32 interval, SDL::NewTimerCallback callback,
			      void *param)
{
	return SDL_AddTimer (interval, callback, param);
}

inline bool RemoveTimer (SDL::TimerID t)
{
	return SDL_RemoveTimer (t);
}

/************************************************************************
 ** file SDL_version.h                                                 **
 ************************************************************************/

typedef SDL_version version;

inline const SDL::version *Linked_Version (void)
{
	return SDL_Linked_Version ();
}

/************************************************************************
 ** file SDL_active.h                                                  **
 ************************************************************************/

const Uint32
	APPMOUSEFOCUS = SDL_APPMOUSEFOCUS,
	APPINPUTFOCUS = SDL_APPINPUTFOCUS,
	APPACTIVE     = SDL_APPACTIVE;

inline Uint32 GetAppState (void)
{
	return SDL_GetAppState ();
}

/************************************************************************
 ** file SDL_cdrom.h                                                   **
 ************************************************************************/

const int
	MAX_TRACKS  = SDL_MAX_TRACKS,
	AUDIO_TRACK = SDL_AUDIO_TRACK,
	DATA_TRACK  = SDL_DATA_TRACK;

} // namespace SDL

// Drop namepace SDL and use namespace CD for these constants.

namespace CD
{
	const CDstatus
		TRAYEMPTY = CD_TRAYEMPTY,
		STOPPED   = CD_STOPPED,
		PLAYING   = CD_PLAYING,
		PAUSED    = CD_PAUSED,
		ERROR     = CD_ERROR;

	inline bool INDRIVE (int status)
	{
		return (status > 0);
	}

	const int
		FPS = CD_FPS;
}

namespace SDL
{

typedef SDL_CDtrack CDtrack;
typedef SDL_CD CD;

inline int CDNumDrives (void)
{
	return SDL_CDNumDrives ();
}

inline const char *CDName (int drive)
{
	return SDL_CDName (drive);
}

inline SDL::CD *CDOpen (int drive)
{
	return SDL_CDOpen (drive);
}

inline CDstatus CDStatus (SDL::CD *cdrom)
{
	return SDL_CDStatus (cdrom);
}

inline int CDPlayTracks (SDL::CD *cdrom, int start_track, int start_frame,
			 int ntracks, int nframes)
{
	return SDL_CDPlayTracks (cdrom, start_track, start_frame,
				 ntracks, nframes);
}

inline int CDPlay (SDL::CD *cdrom, int start, int length)
{
	return SDL_CDPlay (cdrom, start, length);
}

inline int CDPause (SDL::CD *cdrom)
{
	return SDL_CDPause (cdrom);
}

inline int CDResume (SDL::CD *cdrom)
{
	return SDL_CDResume (cdrom);
}

inline int CDStop (SDL::CD *cdrom)
{
	return SDL_CDStop (cdrom);
}

inline int CDEject (SDL::CD *cdrom)
{
	return SDL_CDEject (cdrom);
}

inline void CDClose (SDL::CD *cdrom)
{
	return SDL_CDClose (cdrom);
}

/************************************************************************
 ** file SDL.h                                                         **
 ************************************************************************/

const Uint32
	INIT_TIMER       = SDL_INIT_TIMER,
	INIT_AUDIO       = SDL_INIT_AUDIO,
	INIT_VIDEO       = SDL_INIT_VIDEO,
	INIT_CDROM       = SDL_INIT_CDROM,
	INIT_JOYSTICK    = SDL_INIT_JOYSTICK,
	INIT_NOPARACHUTE = SDL_INIT_NOPARACHUTE,
	INIT_EVENTTHREAD = SDL_INIT_EVENTTHREAD,
	INIT_EVERYTHING  = SDL_INIT_EVERYTHING;

inline int Init (Uint32 flags)
{
	return SDL_Init (flags);
}

inline int InitSubSystem (Uint32 flags)
{
	return SDL_InitSubSystem (flags);
}

inline void QuitSubSystem (Uint32 flags)
{
	SDL_QuitSubSystem (flags);
}

inline Uint32 WasInit (Uint32 flags)
{
	return SDL_WasInit (flags);
}

inline void Quit (void)
{
	SDL_Quit ();
}

/************************************************************************
 ** file SDL_error.h                                                   **
 ************************************************************************/
#include <stdarg.h>

// FIXME: do something with this:
// void SDL_SetError (const char *fmt, ...);
// Okay, perhaps this not the best way but...
inline void SetError (const char *fmt, ...)
{
	char buffer[4096]; // do anyone need longer error message ?
	va_list ap;
	va_start(ap, fmt);
#ifdef HAVE_VSNPRINTF
	vsnprintf(buffer, 4096, fmt, ap);
#else
	vsprintf(buffer, fmt, ap);
#endif
	va_end(ap);
	SDL_SetError (buffer);
}

inline char *GetError (void)
{
	return SDL_GetError ();
}

inline void ClearError (void)
{
	SDL_ClearError ();
}

typedef SDL_errorcode errorcode;

// FIXME: errno.h defines ENOMEM! (This causes problems under GCC 3+)
#ifdef ENOMEM
#undef ENOMEM
#endif // ENOMEM

const SDL::errorcode
	ENOMEM    = SDL_ENOMEM,
	EFREAD    = SDL_EFREAD,
	EFWRITE   = SDL_EFWRITE,
	EFSEEK    = SDL_EFSEEK,
	LASTERROR = SDL_LASTERROR;

inline void Error (SDL::errorcode code)
{
	SDL_Error (code);
}

/************************************************************************
 ** file SDL_image.h                                                   **
 ************************************************************************/

} // drop namespace SDL

namespace IMG
{

#include <SDL/SDL_image.h>

inline SDL::Surface *LoadTyped_RW (SDL::RWops *src, int freesrc, char *type)
{
	return IMG_LoadTyped_RW (src, freesrc, type);
}

inline SDL::Surface *Load (const char *file)
{
	return IMG_Load (file);
}

inline SDL::Surface *Load_RW (SDL::RWops *src, int freesrc)
{
	return IMG_Load_RW (src, freesrc);
}

inline int isBMP (SDL::RWops *src)
{
	return IMG_isBMP (src);
}

inline int isPNM (SDL::RWops *src)
{
	return IMG_isPNM (src);
}

inline int isXPM (SDL::RWops *src)
{
	return IMG_isXPM (src);
}

inline int isXCF (SDL::RWops *src)
{
	return IMG_isXCF (src);
}

inline int isPCX (SDL::RWops *src)
{
	return IMG_isPCX (src);
}

inline int isGIF (SDL::RWops *src)
{
	return IMG_isGIF (src);
}

inline int isJPG (SDL::RWops *src)
{
	return IMG_isJPG (src);
}

inline int isTIF (SDL::RWops *src)
{
	return IMG_isTIF (src);
}

inline int isPNG (SDL::RWops *src)
{
	return IMG_isPNG (src);
}

inline SDL::Surface *LoadBMP_RW (SDL::RWops *src)
{
	return IMG_LoadBMP_RW (src);
}

inline SDL::Surface *LoadPNM_RW (SDL::RWops *src)
{
	return IMG_LoadPNM_RW (src);
}

inline SDL::Surface *LoadXPM_RW (SDL::RWops *src)
{
	return IMG_LoadXPM_RW (src);
}

inline SDL::Surface *LoadXCF_RW (SDL::RWops *src)
{
	return IMG_LoadXCF_RW (src);
}

inline SDL::Surface *LoadPCX_RW (SDL::RWops *src)
{
	return IMG_LoadPCX_RW (src);
}

inline SDL::Surface *LoadGIF_RW (SDL::RWops *src)
{
	return IMG_LoadGIF_RW (src);
}

inline SDL::Surface *LoadJPG_RW (SDL::RWops *src)
{
	return IMG_LoadJPG_RW (src);
}

inline SDL::Surface *LoadTIF_RW (SDL::RWops *src)
{
	return IMG_LoadTIF_RW (src);
}

inline SDL::Surface *LoadPNG_RW (SDL::RWops *src)
{
	return IMG_LoadPNG_RW (src);
}

inline SDL::Surface *LoadTGA_RW (SDL::RWops *src)
{
	return IMG_LoadTGA_RW (src);
}

} // namespace IMG

namespace SDL
{

} // namespace SDL

#endif // __sel_sdl_h__
